package com.xbongbong.pro.statistics.strategy.chart.type.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xbongbong.paas.bi.pojo.vo.DataSetResultVO;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.bi.commons.pojo.AggFieldPojo;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.errorcodes.ChartErrorCodeEnum;
import com.xbongbong.pro.statistic.enums.AdvancedComputingFirstEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartAnalysisVO;
import com.xbongbong.pro.statistics.help.DescribeTableHelper;
import com.xbongbong.pro.statistics.help.DisplayHelper;
import com.xbongbong.pro.statistics.help.InitSqlHelper;
import com.xbongbong.pro.statistics.help.TargetChartVOHelper;
import com.xbongbong.pro.statistics.helper.AggHelper;
import com.xbongbong.pro.statistics.helper.ChartDataSetHelper;
import com.xbongbong.pro.statistics.pojo.dto.ChartAnalysisDTO;
import com.xbongbong.pro.statistics.pojo.dto.GenerateSqlDTO;
import com.xbongbong.pro.statistics.pojo.vo.GenerateSqlVO;
import com.xbongbong.pro.statistics.strategy.chart.type.ChartTypeStrategyService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 指标图
 * @ClassName TargetChartStrategyServiceImpl
 * @Author 梁鲁江
 * 创建时间 2022/9/21 15:42
 * 修改时间  2022/9/21 15:42
 **/
@Service
public class TargetChartStrategyServiceImpl implements ChartTypeStrategyService {
    @Resource
    private DisplayHelper displayHelper;
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private DescribeTableHelper describeTableHelper;
    @Resource
    private ChartDataSetHelper chartDataSetHelper;
    @Resource
    private AggHelper aggHelper;
    @Resource
    private TargetChartVOHelper targetChartVOHelper;
    @Resource
    private InitSqlHelper initSqlHelper;
    @Override
    public ChartAnalysisVO chartAnalysis(ChartAnalysisDTO chartAnalysisDTO) throws XbbException {
        Map<String, Map<String, String>> attrLinkMap = aggHelper.getLinkMap(chartAnalysisDTO.getChartEntity(),  chartAnalysisDTO.getResultArray());
        return targetChartVOHelper.targetChartAnalysis(chartAnalysisDTO,attrLinkMap);
    }

    @Override
    public GenerateSqlVO generateSql(GenerateSqlDTO generateSqlDTO) throws XbbException {
        GenerateSqlVO generateSqlVO = new GenerateSqlVO();
        ChartEntity chartEntity = generateSqlDTO.getChartEntity();
        if (chartEntity.getSummaryAttr().size() <= 0 ) {
            return generateSqlVO;
        }
        ChartResultPojo chartResultPojo = generateSqlDTO.getChartResultPojo();
        List<ChartFieldAttrPojo> groupAttrList = JSONArray.parseArray(chartEntity.getRowGroupAttr().toJSONString(), ChartFieldAttrPojo.class);
        List<FieldAttrPojo> summaryAttrList = JSONArray.parseArray(chartEntity.getSummaryAttr().toJSONString(), FieldAttrPojo.class);
        // 表头处理，渲染时用
        JSONArray tableHead = generateSqlDTO.getTableHead();
        Map<JSONObject, FieldAttrPojo> parseAttrMap = generateSqlDTO.getParseAttrMap();
        Map<String, FieldAttrPojo> summaryAttrMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        handleHeadName4Target(chartEntity, isSingle, formIdTableMap, groupAttrList, tableHead, parseAttrMap);
        List<String> fieldsList = new ArrayList<>();
        for (ChartFieldAttrPojo fieldAttrPojo : groupAttrList) {
            JSONObject headName = displayHelper.setHeadField(chartEntity.getChartType(), fieldAttrPojo);
            tableHead.add(headName);
            parseAttrMap.put(headName, fieldAttrPojo);
            fieldsList.add(fieldAttrPojo.getAttr());
        }
        displayHelper.handleSummary(summaryAttrList, tableHead, parseAttrMap, summaryAttrMap, true);

        // 副指标
        List<FieldAttrPojo> secondTargetList = null;
        if(Objects.nonNull(chartEntity.getSecondTargetAttr())){
            secondTargetList = JSONArray.parseArray(chartEntity.getSecondTargetAttr().toJSONString(), FieldAttrPojo.class);
        }
        List<String> secondTargetKey = new ArrayList<>();
        if (Objects.equals(chartEntity.getChartType(), ChartTypeEnum.SECOND_TARGET_CHART.getCode())){
            if (CollectionUtils.isEmpty(secondTargetList)){
                throw new XbbException(ChartErrorCodeEnum.API_ERROR_310001, ChartErrorCodeEnum.API_ERROR_310001.getMsg());
            }
            FieldAttrPojo fieldAttrPojo = secondTargetList.get(0);
            JSONArray secondAdvancedComputing = fieldAttrPojo.getAdvancedComputing();
            if (CollectionsUtil.isNotEmpty(secondAdvancedComputing) && !Objects.equals(secondAdvancedComputing.getString(0), AdvancedComputingFirstEnum.NONE.getAlias())) {
                // 将副指标里面的统计时间封装成分组字段
                ChartFieldAttrPojo timeAttr = JSONObject.parseObject(chartEntity.getTimeAttr().toJSONString(),ChartFieldAttrPojo.class);
                timeAttr.setLabel(timeAttr.getAttrName());
                timeAttr.setLabelName(timeAttr.getAttrName());
                String timeDimension = fieldAttrPojo.getTimeDimension();
                timeAttr.setDateGroupType(timeDimension);
                groupAttrList.add(timeAttr);
                chartEntity.setRowGroupAttr(JSONArray.parseArray(JSON.toJSONString(groupAttrList)));
                //将时间维度封装成筛选条件
                JSONArray filter = chartEntity.getFilter();
                if (Objects.isNull(filter)){
                    filter = new JSONArray();
                }
                List<Long> valueList = chartResultHelp.getSecondTargetFilter(timeDimension,secondAdvancedComputing,secondTargetKey, null);
                if (CollectionUtils.isNotEmpty(valueList)){
                    JSONObject conditionJson = (JSONObject) JSONObject.toJSON(timeAttr);
                    conditionJson.put("symbol", "range");
                    conditionJson.put("value", valueList);
                    filter.add(conditionJson);
                }
                chartEntity.setFilter(filter);
            }
        }
        //查询条件和筛选条件放在一起
        String filter = describeTableHelper.filterField(chartEntity);
        //String parseSql = chartDataSetHelper.getDataSetParseSql(generateSqlDTO, chartEntity);
        DataSetResultVO dataSetResultVO = chartDataSetHelper.getDataSetParseSql(generateSqlDTO, chartEntity);
        String parseSql = dataSetResultVO.getParseSql();
        Map<String, String> sortFieldMap = displayHelper.getAggSortMap(chartEntity, chartResultPojo.getSortStatisticsMap(),chartResultPojo.getSortFieldOrder());
        Map<String, AggFieldPojo>  aggFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> aggFieldsList = new ArrayList<>();
        //分组字段放在colums
        List<String> groupColumnsList = new ArrayList<>();
        //分组字段放在group by 
        List<String> groupFieldsList = new ArrayList<>();
        List<String> sumTotalFieldsList = new ArrayList<>();
        List<String> subQuerySqlOfCountList = new ArrayList<>();
        List<String> summaryColumnAlisa = new ArrayList<>();
        Boolean isSingle = EsUtil.getSingle(chartEntity);
        Map<String, FieldAttrPojo> comboFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        HashMap<String, Set<String>> selectItemsMap = Maps.newHashMap();
        if (CollectionsUtil.isNotEmpty(groupAttrList)) {
            for (int i = 0; i < groupAttrList.size(); i++) {
                FieldAttrPojo fieldAttrPojo = groupAttrList.get(i);
                if (i == 0) {
                    aggHelper.setGroupField(groupColumnsList, groupFieldsList, fieldAttrPojo, comboFieldMap, chartEntity, sortFieldMap);
//                    groupColumnsList.add(fieldAttrPojo.getAttr());
//                    groupFieldsList.add(fieldAttrPojo.getAttr());
//                    initSqlHelper.addFieldaliasList(selectItemsMap,isSingle, groupColumnsList,groupFieldsList, formIdTableMap,  fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFormId(),sortMap, chartEntity);
                }
            }
            if (CollectionsUtil.isNotEmpty(summaryAttrList)) {
                for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                    Long formId = fieldAttrPojo.getFormId();
                    String attr = fieldAttrPojo.getAttr();
                    String aggType = fieldAttrPojo.getAggType();
                    AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(aggType);
                    //如果是计算字段
                    if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),fieldAttrPojo.getFieldType())) {
                        aggHelper.addComputedField(chartEntity,PaasConstant.LEFT,aggFieldMap,aggFieldsList,fieldAttrPojo,aggTypeEnum,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                    }else{
                        aggHelper.addValuesField(PaasConstant.LEFT, aggFieldMap, aggFieldsList, fieldAttrPojo, aggTypeEnum, attr,sortFieldMap, sumTotalFieldsList,summaryColumnAlisa);
                    }
                }
            }
           /* sourceBuilder.aggregation(tempAggregationBuilder);
            //累加所有桶的值
            SumBucketPipelineAggregationBuilder sumBucket = new SumBucketPipelineAggregationBuilder("sum", aggName1.append('>').append(aggName2).toString());
            sourceBuilder.aggregation(sumBucket);*/
        }else{
            //无分组字段
            //指标有可能是数字，有可能是计数
            if (CollectionsUtil.isNotEmpty(summaryAttrList)) {
                for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                    Long formId = fieldAttrPojo.getFormId();
                    String attr = fieldAttrPojo.getAttr();
                    String aggType = fieldAttrPojo.getAggType();
                    AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(aggType);
                    //如果是计算字段，需要判断是否是计算字段
                    if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),fieldAttrPojo.getFieldType())) {
                        aggHelper.addComputedField(chartEntity,PaasConstant.LEFT,aggFieldMap,aggFieldsList,fieldAttrPojo,aggTypeEnum,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                    }else{
                        aggHelper.addValuesField(PaasConstant.LEFT, aggFieldMap, aggFieldsList, fieldAttrPojo, aggTypeEnum, attr,sortFieldMap, sumTotalFieldsList,summaryColumnAlisa);
                    }
                }
            }
        }
        GroupSqlVO groupSqlVO = GroupSqlVO.initGroupSqlVO(comboFieldMap,groupFieldsList);
        groupSqlVO.setSubQuerySqlOfCountList(subQuerySqlOfCountList);
        groupSqlVO.setSummaryColumnAlisa(summaryColumnAlisa);
        initSqlHelper.buildSubColumnOfCount(groupSqlVO,groupColumnsList,Boolean.FALSE);

        groupColumnsList.addAll(aggFieldsList);
        //","分割
        String colums = String.join(XbbConstant.SQL_COMMA, groupColumnsList);
        String groupFields = String.join(XbbConstant.SQL_COMMA, groupFieldsList);
        String sortField = displayHelper.getDsAggSortField(sortFieldMap,groupSqlVO);
        StringBuffer sql = chartDataSetHelper.tableSqlAppend(parseSql, colums, sortField, filter, 100, 0, groupFields, false, groupSqlVO);
        //分页
        Integer page = chartResultPojo.getPage() == null ? 1 : chartResultPojo.getPage();
        Integer pageSize = chartResultPojo.getPageSize() == null ? 20 : chartResultPojo.getPageSize();
        PageHelper pageHelper = new PageHelper(page, pageSize);
        generateSqlVO.setPageHelper(pageHelper);
        generateSqlVO.setStringBufferSql(sql);
        generateSqlVO.setAggFieldMap(aggFieldMap);
        generateSqlVO.setSummaryAttrMap(summaryAttrMap);
        generateSqlVO.setSecondTargetKey(secondTargetKey);
        
        return generateSqlVO;
    }
}
